/*
 * @(#)DocumentEntryTypeTransformer.java
 * Date 2013-09-02
 * Version 1.0
 * DocumentEntryAuthor Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.transformer.xds;

import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.ClassificationType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ExternalIdentifierType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ExtrinsicObjectType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.SlotType1;

import org.apache.commons.lang3.StringUtils;

import org.joda.time.DateTime;

import us.hornerscorners.lamppost.exception.ServiceActionException;

import us.hornerscorners.lamppost.hl7v3common.utils.HL7Utils;

import us.hornerscorners.lamppost.model.common.CodedElement;
import us.hornerscorners.lamppost.model.common.InstanceIdentifier;
import us.hornerscorners.lamppost.model.common.TimeInterval;

import us.hornerscorners.lamppost.model.document.DocumentEntry;

import us.hornerscorners.lamppost.registry.constant.Metadata;
import us.hornerscorners.lamppost.registry.constant.SlotName;

import us.hornerscorners.lamppost.transformer.AbstractTransformer;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-02
 * @author         Jim Horner
 */
@ApplicationScoped
public class DocumentEntryTypeTransformer
        extends AbstractTransformer<DocumentEntry, ExtrinsicObjectType> {

    /** Field description */
    @Inject
    private ClassificationTypeTransformer classificationTransformer;

    /** Field description */
    @Inject
    private ExternalIdentifierTypeTransformer externalIdentifierTransformer;

    /** Field description */
    @Inject
    private InternationalStringTypeTransformer internationalStringTransformer;

    /** Field description */
    @Inject
    private SlotTypeTransformer slotTransformer;

    /** Field description */
    @Inject
    private VersionInfoTypeTransformer versionInfoTransformer;

    /**
     * Constructs ...
     *
     */
    public DocumentEntryTypeTransformer() {
        super();
    }

    /**
     * Method description
     *
     *
     * @param doc
     *
     * @return
     */
    @Override
    public ExtrinsicObjectType transform(DocumentEntry doc)
            throws ServiceActionException {

        ExtrinsicObjectType result = new ExtrinsicObjectType();

        // ***********
        // attributes

        result.setId(doc.getEntryURN());
        result.setMimeType(doc.getMimeType());
        result.setStatus(doc.getAvailabilityStatus().getCode());
        result.setObjectType(Metadata.DocumentEntryClassificationNode.getURN());

        // versioning
        result.setLid(doc.getEntryLogicalURN());
        result.setVersionInfo(
            this.versionInfoTransformer.transform(doc.getEntryVersion()));

        // *******
        // slots
        List<SlotType1> slots = result.getSlot();

        DateTime creationTime = doc.getCreationTime();

        if (creationTime != null) {

            slots.add(this.slotTransformer.transform(SlotName.CreationTime,
                    creationTime));
        }

        String hash = doc.getHash();

        if (StringUtils.isNotBlank(hash)) {
            slots.add(this.slotTransformer.transform(SlotName.Hash, hash));
        }

        String languageCode = doc.getLanguageCode();

        if (StringUtils.isNotBlank(languageCode)) {

            slots.add(this.slotTransformer.transform(SlotName.LanguageCode,
                    languageCode));
        }

        String repositoryId = doc.getRepositoryId();

        if (StringUtils.isNotBlank(repositoryId)) {

            slots.add(this.slotTransformer.transform(SlotName.RepositoryUniqueId,
                    repositoryId));
        }

        TimeInterval serviceInterval = doc.getServiceInterval();

        if (serviceInterval != null) {

            DateTime serviceStart = serviceInterval.getStart();

            if (serviceStart != null) {

                slots.add(this.slotTransformer.transform(SlotName.ServiceStartTime,
                        serviceStart));
            }

            DateTime serviceStop = serviceInterval.getStop();

            if (serviceStop != null) {

                slots.add(this.slotTransformer.transform(SlotName.ServiceStopTime,
                        serviceStop));
            }
        }

        String size = doc.getSize();

        if (StringUtils.isNotBlank(size)) {

            slots.add(this.slotTransformer.transform(SlotName.Size, size));
        }

        InstanceIdentifier sourcePatientId = doc.getSourcePatientId();

        if (sourcePatientId != null) {

            slots.add(this.slotTransformer.transform(SlotName.SourcePatientId,
                    HL7Utils.toCXString(sourcePatientId)));
        }

        List<String> sourcePatientInfo = doc.getSourcePatientInfo();

        if (sourcePatientInfo.isEmpty() == false) {

            slots.add(this.slotTransformer.transform(SlotName.SourcePatientInfo,
                    sourcePatientInfo));
        }

        // ************
        // extra slots

        slots.addAll(this.slotTransformer.transform(doc.getExtraAttributes()));

        // *********
        // elements

        result.setName(
            this.internationalStringTransformer.transform(doc.getDisplayNames()));

        result.setDescription(
            this.internationalStringTransformer.transform(doc.getDescriptions()));

        // **************
        // classification

        List<ClassificationType> classifications = result.getClassification();

        // author
        classifications.addAll(
            this.classificationTransformer.transformAuthors(
                Metadata.DocumentEntryAuthor, doc, doc.getAuthors()));

        // class code

        CodedElement classCode = doc.getClassCode();

        if (classCode != null) {

            classifications.add(
                this.classificationTransformer.transformCodedElement(
                    Metadata.DocumentEntryClassCode, doc, classCode));
        }

        // confidentiality codes

        classifications.addAll(
            this.classificationTransformer.transformCodedElements(
                Metadata.DocumentEntryConfidentialityCode, doc,
                doc.getConfidentialityCodes()));

        // event codes

        classifications.addAll(
            this.classificationTransformer.transformCodedElements(
                Metadata.DocumentEntryEventCode, doc, doc.getEventCodes()));

        // format code

        CodedElement formatCode = doc.getFormatCode();

        if (formatCode != null) {

            classifications.add(
                this.classificationTransformer.transformCodedElement(
                    Metadata.DocumentEntryFormatCode, doc, formatCode));
        }

        // healthcare facility type code

        CodedElement healthcareCode = doc.getHealthcareFacilityTypeCode();

        if (healthcareCode != null) {

            classifications.add(
                this.classificationTransformer.transformCodedElement(
                    Metadata.DocumentEntryHealthCareFacilityTypeCode, doc,
                    healthcareCode));
        }

        // practice setting code

        CodedElement practiceCode = doc.getPracticeSettingCode();

        if (practiceCode != null) {

            classifications.add(
                this.classificationTransformer.transformCodedElement(
                    Metadata.DocumentEntryPracticeSettingCode, doc, practiceCode));
        }

        // type code

        CodedElement typeCode = doc.getTypeCode();

        if (typeCode != null) {

            classifications.add(
                this.classificationTransformer.transformCodedElement(
                    Metadata.DocumentEntryTypeCode, doc, typeCode));
        }

        // *********************
        // external identifiers

        List<ExternalIdentifierType> externalIds = result.getExternalIdentifier();

        externalIds.add(
            this.externalIdentifierTransformer.transformPatientIdentifier(
                Metadata.DocumentEntryPatientId, doc, doc.getPatientId()));

        externalIds.add(
            this.externalIdentifierTransformer.transformUniqueIdentifier(
                Metadata.DocumentEntryUniqueId, doc, doc.getUniqueId()));

        return result;
    }
}
